package com.bupt.godxian.charging.controller;

import com.bupt.godxian.charging.config.ApplicationProperties;
import com.bupt.godxian.charging.config.CommonResponse;
import com.bupt.godxian.charging.entity.ChargeRequest;
import com.bupt.godxian.charging.entity.User;
import com.bupt.godxian.charging.service.*;
import com.bupt.godxian.charging.util.JwtUtil;
import com.bupt.godxian.charging.util.Timer;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import static org.hibernate.action.internal.BulkOperationCleanupAction.schedule;

@Slf4j
@RestController
@CrossOrigin(origins = "*", allowedHeaders = "Authorization")
@RequestMapping("/user")
public class UserController {

    private  final UserService userService;

    private final ApplicationProperties applicationProperties;

    @Autowired
    public UserController(UserService userService, ApplicationProperties applicationProperties) {
        this.userService = userService;
        this.applicationProperties = applicationProperties;
    }

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private ChargeRequestService chargeRequestService;

    @Autowired
    private WaitQueueService waitQueueService;

    @Autowired
    private WaitAreaService waitAreaService;

    @Autowired
    private ScheduleService scheduleService;


//    @PutMapping("/{id}")
//    public ResponseEntity<?> updateUser(@PathVariable Long id, @RequestBody User user) {
//        user.setId(id);
//        userService.update(user);
//        return ResponseEntity.ok().build();
//    }
//
//    @DeleteMapping("/{id}")
//    public ResponseEntity<?> deleteUser(@PathVariable Integer id) {
//        userService.delete(id);
//        return ResponseEntity.ok().build();
//    }
//
//    @GetMapping("/{id}")
//    public ResponseEntity<User> getUserById(@PathVariable Integer id) {
//        User user = userService.findById(id);
//        return ResponseEntity.ok(user);
//    }
//
//    @GetMapping("/username/{username}")
//    public ResponseEntity<User> getUserByUsername(@PathVariable String username) {
//        User user = userService.findByUsername(username);
//        return ResponseEntity.ok(user);
//    }

    //提交充电请求
    @PostMapping("/submit_charging_request")
    public ResponseEntity<CommonResponse> submitChargingRequest(@RequestBody Map<String, Object> request,@RequestHeader("Authorization") String tokenHeader) {
            // 验证JWT令牌的合法性
            if (jwtUtil.dependToken(tokenHeader)) {
            // 获取当前用户
            String username = jwtUtil.getUsernameFromToken(jwtUtil.token);
            User user = userService.findByUsername(username);

            // 获取充电请求参数
            String chargeMode = (String) request.get("charge_mode");
            Double requireAmount = (Double) request.get("require_amount");
            Double batterySize = (Double) request.get("battery_size");

            // TODO(1): 处理，获取 chargeId
            // 判断是否不在充电状态:没有充电记录或者不存在待充电请求则代表不在充电状态
            ChargeRequest record = chargeRequestService.getChargeRequestByUserId(user.getId());
            ChargeRequest undoRecord = chargeRequestService.getUndoChargeRequestByUserId(user.getId());
            BigDecimal chargeTime = null;

            boolean success = true;
            String error_msg = null;
            String charge_id = null;
            //只有在有充电记录同时存在待充电请求时才说明在充电状态,而只有在充电时不能请求充电
            if (record == null || undoRecord == null) {
                //只保留最新的请求
                if (undoRecord!=null){
                    success = false;
                    error_msg = "请求失败，还存在未完成的充电请求。";
                }else {
                    // 插入对应队列 state1是正在等候充电的状态，这里从数据库中查询当前等候充电数量
                    // 1 等候充电 2充电区等候充电？  3正在充电
                    if (waitQueueService.getWaitQueueCount(1) < applicationProperties.getN()) {
                        //如果等待队列中有空间，它会根据 和现有请求的 ID 为新请求生成
                        // 生成 chargeId, 加入队列
                        int hisFrontCars = chargeRequestService.getHisFrontCarsCount(chargeMode);

                        if (hisFrontCars == 0) {
                            charge_id = chargeMode + '1';
                        } else {
                            List<ChargeRequest> resRaw = chargeRequestService.findByChargeModeAndStateNotZero(chargeMode);
                            int res = resRaw.stream()
                                    .map(chargeRequest -> Integer.parseInt(chargeRequest.getChargeId().substring(1)))
                                    .max(Integer::compare)
                                    .orElse(0);
                            charge_id = chargeMode + (res + '1');
                        }
                        if (chargeMode.equals("F")) {
                            chargeTime = BigDecimal.valueOf(requireAmount).divide(BigDecimal.valueOf(applicationProperties.getF_power()), RoundingMode.HALF_UP)
                                    .multiply(BigDecimal.valueOf(3600));
                        } else if (chargeMode.equals("T")) {
                            chargeTime = BigDecimal.valueOf(requireAmount).divide(BigDecimal.valueOf(applicationProperties.getT_power()), RoundingMode.HALF_UP)
                                    .multiply(BigDecimal.valueOf(3600));
                        }

                        // 生成充电请求，插入数据库
                        Timer timer = new Timer();
                        long submitTime = timer.getCurTimestamp();
                        ChargeRequest chargeRequest = new ChargeRequest();
                        chargeRequest.setState(1);
                        chargeRequest.setUserId(String.valueOf(user.getId()));
                        chargeRequest.setChargeMode(chargeMode);
                        chargeRequest.setRequireAmount(requireAmount);
                        chargeRequest.setChargeTime(chargeTime);
                        chargeRequest.setBatterySize(batterySize);
                        chargeRequest.setChargeId(charge_id);
                        chargeRequest.setRequestSubmitTime(BigDecimal.valueOf(submitTime));
                        //插入请求是否需要添加判断，不然容易陷入添加了请求但是没有等候之后无法添加的情况？
                        chargeRequestService.createChargeRequest(chargeRequest);

                        // WaitArea 等候区队列处理
                        waitAreaService.addWaitArea(Long.valueOf(chargeRequest.getId()), chargeMode);

                        waitQueueService.addWaitQueue(chargeMode, charge_id);

                        // 如果等待区不为空要调度:似乎只需要调度程序对WaitQueue中state=1的记录不断进行调度即可
                        scheduleService.schedule(2, Long.valueOf(chargeRequest.getId()),null,null,false,false);


                    }
                    else {
                        success = false;
                        error_msg = "请求失败，等候区已满。";
                    }
                }

            } else {
                success = false;
                error_msg = "请求失败，还有待完成充电请求。";

            }
            if (success) {
                Map<String, Object> ChargeResponseData = new HashMap<>();
                ChargeResponseData.put("charge_id", charge_id);
                return ResponseEntity.ok(new CommonResponse(0, "Success", ChargeResponseData));
            } else {
                return ResponseEntity.ok(new CommonResponse(-1, error_msg));
            }

        }
        else{
            return ResponseEntity.ok(new CommonResponse(-1, "Invalid token!"));}

    }



    @PostMapping("/edit_charging_request")
    public ResponseEntity<?> editChargingRequest(@RequestBody Map<String, Object> request,@RequestHeader("Authorization") String tokenHeader) {
        // 验证JWT令牌的合法性
        if (jwtUtil.dependToken(tokenHeader)){
            // 获取当前用户
            String username = jwtUtil.getUsernameFromToken(jwtUtil.token);
            User user = userService.findByUsername(username);

            // 获取充电请求参数
            String chargeMode = (String) request.get("charge_mode");
            Double requireAmount = (Double) request.get("require_amount");
            // TODO(1): 处理，修改充电请求
            //Service操作
            CommonResponse result=userService.edit_charging_request(user,chargeMode,requireAmount);

            return ResponseEntity.ok(result);
        }  else{
            return ResponseEntity.ok(new CommonResponse(-1, "Invalid token!"));}

    }


    //@RequestBody Map<String, Object> request,
    @GetMapping("/end_charging_request")
    public ResponseEntity<?> endChargingRequest(@RequestHeader("Authorization") String tokenHeader) {
        // 验证JWT令牌的合法性
        if (jwtUtil.dependToken(tokenHeader)){
            // 获取当前用户
            String username = jwtUtil.getUsernameFromToken(jwtUtil.token);
            User user = userService.findByUsername(username);

            // 获取充电请求参数
//            String chargeMode = (String) request.get("charge_mode");
//            Double requireAmount = (Double) request.get("require_amount");
            // TODO(2): 处理，取消充电请求
            //Service操作
            CommonResponse result = userService.end_charging_request(user);

            return ResponseEntity.ok(result);
        }  else{
            return ResponseEntity.ok(new CommonResponse(-1, "Invalid token!"));}

    }

    //查看账单
    @GetMapping("/query_bill")
    public ResponseEntity<?> querybill(@RequestHeader("Authorization") String tokenHeader) {
        // 验证JWT令牌的合法性
        if (jwtUtil.dependToken(tokenHeader)){
            // 获取当前用户
            String username = jwtUtil.getUsernameFromToken(jwtUtil.token);
            User user = userService.findByUsername(username);

            //TODO(2): 处理，获取该用户账单  √
            //Service操作
            Map<String, Object> result=  userService.query_bill(user);

            return ResponseEntity.ok(result);
        }  else{
            return ResponseEntity.ok(new CommonResponse(-1, "Invalid token!"));}

    }
    //查看详单:@RequestBody Map<String, Object> request直接返回所有
    @GetMapping("/query_order_detail")
    public ResponseEntity<?> queryOrderDetail(@RequestHeader("Authorization") String tokenHeader) {
        // 验证JWT令牌的合法性
        if (jwtUtil.dependToken(tokenHeader)){
            // 获取当前用户
            String username = jwtUtil.getUsernameFromToken(jwtUtil.token);
            User user = userService.findByUsername(username);

//            // 获取详单请求参数bill_id
//            String order_id = (String) request.get("order_id");
            //TODO(2): 处理，获取该用户所有充电详单  √
            //Service操作
            Map<String, Object> result=userService.query_order_detail(user);

            return ResponseEntity.ok(result);
        }  else{
            return ResponseEntity.ok(new CommonResponse(-1, "Invalid token!"));}

    }

    @GetMapping("/preview_queue")
    public ResponseEntity<?> preview_queue(@RequestHeader("Authorization") String tokenHeader) throws JsonProcessingException {

//    public ResponseEntity<?> preview_queue(@RequestBody Map<String, Object> request,@RequestHeader("Authorization") String tokenHeader) throws JsonProcessingException {
        // 验证JWT令牌的合法性
        if (jwtUtil.dependToken(tokenHeader)){
            // 获取当前用户
            String username = jwtUtil.getUsernameFromToken(jwtUtil.token);
            User user = userService.findByUsername(username);

            // 获取充电请求参数
//            String chargeMode = (String) request.get("charge_mode");
//            Double requireAmount = (Double) request.get("require_amount");
            // TODO(1): 处理，获取排队详情
            //Service操作
            CommonResponse result=userService.preview_queue(user);//, chargeMode, requireAmount

            return ResponseEntity.ok(result);
        }  else{
            return ResponseEntity.ok(new CommonResponse(-1, "Invalid token!"));}

    }


}
